home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_087
/
id-handler
/
id-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
7KB
|
295 lines
/****************************************************************************
** File: ID-handler.c
** Program: ID-handler - an AmigaDOS handler for generating unique names
** Version: 1.0
** Author: Ed Puckett qix@mit-oz
**
** Copyright 1987 EpAc Software. All Rights Reserved.
**
** History: 02-Feb-87 Original Version
*/
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <exec/exec.h>
#include <ctype.h>
/*---------------------------------------------------------------------------
** References to system
*/
extern struct Library *OpenLibrary ();
extern void CloseLibrary ();
extern struct Task *FindTask ();
extern ULONG Wait ();
extern struct Message *GetMsg ();
extern void PutMsg ();
extern BYTE *AllocMem ();
extern void FreeMem ();
extern struct Library *AbsExecBase;
/*---------------------------------------------------------------------------
** These are new to the 1.2 release
*/
#ifndef MODE_READWRITE
# define MODE_READWRITE 1004
#endif MODE_READWRITE
#ifndef MODE_READONLY
# define MODE_READONLY MODE_OLDFILE
#endif MODE_READONLY
#ifndef ACTION_END
# define ACTION_END 1007 /* not really new, just missing */
#endif ACTION_END
/*---------------------------------------------------------------------------
*/
#define ALLOCMEM_FLAGS MEMF_PUBLIC
#define ID_DIGITS 16
typedef struct opendata
{ char id[ID_DIGITS];
UBYTE pos;
}
OPENDATA;
struct Library *SysBase = NULL;
struct Library *DOSBase = NULL;
static char ID[ID_DIGITS];
/*---------------------------------------------------------------------------
*/
#define BPTRtoCptr(Bp) ((char *) ((ULONG) (Bp) << 2))
#define CptrtoBPTR(Cp) ((BPTR) ((ULONG) (Cp) >> 2))
#define ReplyPkt(pkt) PutMsg ((pkt)->dp_Port, (pkt)->dp_Link)
/*---------------------------------------------------------------------------
** handler() performs initialization, replies to startup packet, and
** dispatches incoming request packets to the apropriate functions.
** Our DeviceNode Task field is patched with our process ID so that this
** process is used for subsequent handler requests. The function exits only
** if there is some initialization error.
*/
void handler (StartPkt)
struct DosPacket *StartPkt;
{ struct Task *Task;
struct MsgPort *IDPort;
ULONG WakeupMask, SigMask;
struct DeviceNode *DevNode;
struct DosPacket *pkt, *GetPkt();
unsigned i;
void OpenID(), CloseID(), ReadID();
SysBase= AbsExecBase;
if ((DOSBase= OpenLibrary (DOSNAME, 0)) == NULL)
goto QUIT;
Task= FindTask (0);
IDPort= (struct MsgPort *) ((ULONG) Task + sizeof (struct Task));
((struct Process *) Task)->pr_CurrentDir= 0; /* initial file system root */
WakeupMask= (1L << IDPort->mp_SigBit);
DevNode= (struct DeviceNode *) BPTRtoCptr (StartPkt->dp_Arg3);
DevNode->dn_Task= IDPort;
ReplyPkt (StartPkt);
for (i= 0; i < ID_DIGITS; ++i)
ID[i]= '0';
LOOP:
SigMask= Wait (WakeupMask);
if (SigMask & WakeupMask)
while ((pkt= GetPkt (IDPort)) != NULL)
switch (pkt->dp_Type)
{ case MODE_READWRITE:
OpenID (pkt);
break;
case MODE_NEWFILE: /* syn: ACTION_FINDOUTPUT */
pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_WRITE_PROTECTED;
ReplyPkt (pkt);
break;
case MODE_READONLY: /* syn: MODE_OLDFILE, ACTION_FINDINPUT */
OpenID (pkt);
break;
case ACTION_END:
CloseID (pkt);
break;
case ACTION_READ:
ReadID (pkt);
break;
case ACTION_WRITE:
pkt->dp_Res1= -1;
pkt->dp_Res2= ERROR_WRITE_PROTECTED;
ReplyPkt (pkt);
break;
default:
pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_ACTION_NOT_KNOWN;
ReplyPkt (pkt);
}
goto LOOP;
QUIT:
DevNode->dn_Task= NULL; /* bad if someone in process of accessing us . . . */
if (DOSBase != NULL)
CloseLibrary (DOSBase);
}
/*---------------------------------------------------------------------------
** GetPkt() returns the DosPacket associated with the next message on
** "port", or NULL if the port is empty. The message is removed from the
** port. A related macro, ReplyPkt(), is provided above.
*/
static struct DosPacket *GetPkt (port)
register struct MsgPort *port;
{ register struct Message *msg;
return ((msg= GetMsg (port)) == NULL)
? NULL
: (struct DosPacket *) msg->mn_Node.ln_Name;
}
/*---------------------------------------------------------------------------
*/
static void OpenID (pkt)
struct DosPacket *pkt;
{ struct FileHandle *handle;
OPENDATA *OpenData = NULL;
unsigned i;
void NextID();
if ((OpenData= (OPENDATA *) AllocMem (sizeof (OPENDATA), ALLOCMEM_FLAGS)) == NULL)
{ pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_NO_FREE_STORE;
ReplyPkt (pkt);
}
for (i= 0; i < ID_DIGITS; ++i)
OpenData->id[i]= ID[i];
OpenData->pos= 0;
NextID ();
handle= (struct FileHandle *) BPTRtoCptr (pkt->dp_Arg1);
handle->fh_Arg1= (LONG) OpenData; /* for identification on Read, Close */
pkt->dp_Res1= 1;
pkt->dp_Res2= 0; /* for successful open */
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
*/
static void CloseID (pkt)
struct DosPacket *pkt;
{ OPENDATA *OpenData;
OpenData= (OPENDATA *) pkt->dp_Arg1;
FreeMem (OpenData, sizeof (OPENDATA));
pkt->dp_Res1= 1;
pkt->dp_Res2= 0;
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
*/
static void ReadID (pkt)
struct DosPacket *pkt;
{ OPENDATA *OpenData;
unsigned n;
OpenData= (OPENDATA *) pkt->dp_Arg1;
pkt->dp_Res1= 0;
if (OpenData->pos < ID_DIGITS)
{ if ((n= pkt->dp_Arg3) > (ID_DIGITS - OpenData->pos))
n= (ID_DIGITS - OpenData->pos);
for ( ; pkt->dp_Res1 < n; ++(pkt->dp_Res1), ++(OpenData->pos))
((char *) pkt->dp_Arg2)[pkt->dp_Res1]= OpenData->id[OpenData->pos];
}
pkt->dp_Res2= 0;
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
*/
static void NextID ()
{ int i;
for (i= ID_DIGITS - 1; (i >= 0) && (++(ID[i]) > '9'); --i)
ID[i]= '0';
}